import React, { useState, useEffect } from 'react'
import { Form, Radio, Select, Button, Input } from 'antd'

import ProductSpecTable from '@/components/product/productSpecTable'
import ProductSpecForm from '@/components/product/productSpecForm'

import { tips } from '@/utils/message'

// 单规格时的规格列表，多规格时也需要
const defaultSingle = {
  price: 0,
  pic: null,
  cost: 0,
  ot_price: 0,
  stock: 0,
  bar_code: '',
  weight: 0,
  volume: 0,
}

/**
 * 递归取sku的方法（属性组合）
 * @param {array} list 动态表单获取到的列表
 * @param {number} sort 序号，用于生成属性名
 * @param {array} prev 新列表容器，每一次递归获取到的数据都塞到这里面
 * @returns {object} 获取到的sku数组
 */
function getSku(list, sort, prev, single) {
  const curr = list[sort]
  // 列表没有长度就表示循环结束了
  if (sort === list.length - 1) {
    // 循环结束表示到了最底层，将single里的添加进来
    return curr.detail.map(item => ({ ...prev, [`attr_${sort}`]: item, ...single }))
  }
  // 返回可用的sku数组
  return curr.detail.map(item =>
    getSku(list, sort + 1, { ...prev, [`attr_${sort}`]: item }, single)
  )
}

/**
 * 因规格表单比较复杂，这块仍然拆分了两个子组件出去，一个是动态表单，一个是规格列表
 * productSpec组件主要负责处理显示与隐藏逻辑以及输入完成后将数据发送给主表单域的工作
 * @param {*} props
 * @returns
 */
export default function ProductSpec(props) {
  // 规格类型 (0: 单规格; 1: 多规格) 默认为单规格
  const [specType, setSpecType] = useState(0)
  // 规格列表（注意，规格列表有两处修改数据，本页的选择规格与子组件的规格修改）
  const [specs, setSpecs] = useState([])
  // 多规格时的表头，因为动态表单中的内容不确定，所以需要每次手动生成
  const [skuColumns, setSkuColumns] = useState([])
  const [skus, setSkus] = useState([])
  // 是否显示动态表单
  const [formVisible, changeFormVisible] = useState(false)
  // 是否显示多规格表格
  const [skusVisible, changeSkusVisible] = useState(false)

  /**
   * 副作用
   * 当specType属性发生变化时，判断是否需要将表格切换成单规格
   */
  useEffect(() => {
    // 单规格
    if (specType === 0) {
      props.form.setFieldsValue({ attrs: [defaultSingle] })
      // 不显示动态表单
      changeFormVisible(false)
      // 不显示多规格列表的表头
      changeSkusVisible(false)
    }
  }, [specType, props.form])

  /**
   * 显示动态表单内容
   */
  const handlerFormVisible = () => {
    // 未选择规格前不允许展开
    if (!specs.length) {
      return tips.warn('请选择规格后确认')
    }
    changeFormVisible(true)
  }

  /**
   * 动态表单的内容添加完成，需要更新规格列表
   * 这个方法会往下传
   */
  const updateSpecList = (type, index) => {
    if (type === 'clean') {
      return props.form.setFieldsValue({ modify: [{}] })
    }

    let attrs
    if (type === 'modify') {
      const single = props.form.getFieldsValue()['modify'][0]
      attrs = getSku([...specs], 0, {}, single).flat(Infinity)
    }

    if (type === 'delete') {
      attrs = skus.splice(index, 1)
    }

    if (type === 'init') {
      attrs = getSku([...specs], 0, {}, defaultSingle).flat(Infinity)
      // 生成新的表头
      setSkuColumns(
        specs.map((item, index) => ({
          title: item.value,
          dataIndex: `attr_${index}`,
          render: i => {
            // 注意这里，只要item的name属性是正确的，form表单会自动回填数据
            return (
              <Form.Item name={[i, `attr_${index}`]}>
                {/* 因为要form表单自动回填数据，这里只能使用input */}
                <Input disabled bordered={false} />
              </Form.Item>
            )
          },
        }))
      )
      // 展示列表
      changeSkusVisible(true)
    }
    props.form.setFieldsValue({ attrs })
    setSkus(attrs)
  }

  return (
    <div className="spec-wrap">
      {/* 规格切换 */}
      <Form.Item name="specSelect" label="商品规格" initialValue={specType}>
        {/* 手动进行规格切换 */}
        <Radio.Group onChange={({ target }) => setSpecType(target.value)}>
          <Radio value={0}>单规格</Radio>
          <Radio value={1}>多规格</Radio>
        </Radio.Group>
      </Form.Item>

      {/* 商品规格：单规格时仅显示规格表格，无其它任意功能 */}
      {specType === 0 && <ProductSpecTable />}

      {/* 多规格时先渲染一个动态表单配置sku */}
      {specType === 1 && (
        <Form.Item className="spec-wrap" label="选择规格">
          <Select
            className="half"
            options={props.specList}
            placeholder="请选择规格"
            onChange={(_, { list }) => setSpecs(list)}
          />
          {/* Form.Item中只要存在按钮，antd会提示你不允许往这个Item上添加name属性。
              表示这个Item会脱离表单域，自主处理，待提交的属性中也不会包含这个Item */}
          <Button type="primary" onClick={handlerFormVisible}>
            确认
          </Button>
          {/* 懒，这块就不写了，逻辑与现有的动态表单逻辑差不多。。 */}
          <Button>添加规格</Button>
        </Form.Item>
      )}

      {/* 动态表单 */}
      {formVisible && (
        <ProductSpecForm
          specs={specs} // 当前规格已经包含的属性列表
          setSpecs={setSpecs} // 新增规格属性的方法
          updateSpecList={updateSpecList} // 规格确认后渲染
        />
      )}

      {/* sku表格 */}
      {skusVisible && (
        <>
          {/* 多规格的统一配置表格 它的值改变会影响sku列表中所有的属性 */}
          <div>批量设置：</div>
          <ProductSpecTable updateSpecList={updateSpecList} />
          {/* sku表格 这是当前组件唯一需要传入表单的内容 */}
          <div>商品属性：</div>
          <ProductSpecTable skuColumns={skuColumns} />
        </>
      )}
    </div>
  )
}